﻿#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <fcntl.h>
#include <unistd.h>

// 刷新方式
#define LINE_FLUSH 0x1

// 自定义 FILE 结构
struct MYFILE {
    int fileno;               // 文件描述符
    int flag;                 // 打开标志
    int bufferlen;            // 缓冲区中已用字节数
    char outbuffer[1024];     // 输出缓冲区
    int flush_method;         // 刷新策略
};

// 创建并初始化 MYFILE 对象
static MYFILE* BuyFile(int fd, int flag) {
    MYFILE* f = new MYFILE();
    if (f == nullptr) return nullptr;

    f->bufferlen = 0;
    f->fileno = fd;
    f->flag = flag;
    f->flush_method = LINE_FLUSH;
    memset(f->outbuffer, 0, sizeof(f->outbuffer));

    return f;
}

// 自定义 fopen
MYFILE* MYFopen(const char* path, const char* mode) {
    int fd = -1;
    int flag = 0;

    if (strcmp(mode, "w") == 0) {
        flag = O_CREAT | O_WRONLY | O_TRUNC;
        fd = open(path, flag, 0666);
    }
    else if (strcmp(mode, "a") == 0) {
        flag = O_CREAT | O_WRONLY | O_APPEND;
        fd = open(path, flag, 0666);
    }
    else if (strcmp(mode, "r") == 0) {
        flag = O_RDONLY;
        fd = open(path, flag);
    }
    else {
        // 非法模式
        return nullptr;
    }

    if (fd < 0) return nullptr;

    return BuyFile(fd, flag);
}
// 自定义 fflush
void MYFflush(MYFILE* file) {
    if (file == nullptr || file->bufferlen == 0) return;

    ssize_t n = write(file->fileno, file->outbuffer, file->bufferlen);
    if (n < 0) {
        perror("write failed");
    }
    file->bufferlen = 0;
}
// 自定义 fclose
void MYFclose(MYFILE* file) {
    if (file) {
        MYFflush(file);  // 关闭前刷新
        close(file->fileno);
        delete file;
    }
}



// 自定义 fwrite
int MYFwrite(MYFILE* file, const void* str, int len) {
    if (file == nullptr || str == nullptr || len <= 0) return 0;

    // 如果缓冲区装不下，先刷新
    if (file->bufferlen + len > (int)sizeof(file->outbuffer)) {
        MYFflush(file);
    }

    // 拷贝到缓冲区
    memcpy(file->outbuffer + file->bufferlen, str, len);
    file->bufferlen += len;

    // 行缓冲：遇到 '\n' 就刷新
    if ((file->flush_method & LINE_FLUSH) && file->outbuffer[file->bufferlen - 1] == '\n') {
        MYFflush(file);
    }

    return len;
}

int main() {
    MYFILE* fp = MYFopen("test.txt", "w");
    if (!fp) {
        perror("MYFopen failed");
        return 1;
    }

    const char* msg1 = "Hello, world!\n";
    const char* msg2 = "This is a test.\n";

    MYFwrite(fp, msg1, strlen(msg1));
    MYFwrite(fp, msg2, strlen(msg2));

    MYFclose(fp);
    return 0;
}